package components;


import graphNew.DinicMainGraph;
import graphNew.FlowingEdge;
import graphNew.MainGraph;

import java.util.HashSet;
import java.util.Set;

import main.Translating;

import org.jgrapht.graph.DefaultDirectedWeightedGraph;

/**
 * the agent class
 * @author dannysi
 *
 */

public class Agent {
	
	
	/*id counter*/
	private static int idCounter=0;
	//id of the agent
	private int agentId;
	//the operators of the agent
	private HashSet<Operator> operators;
	//the graph the agent represent
	private DinicMainGraph agentGraph;
	//the rank of the agent 
	private double rank;
	private boolean splitable;
	private int edgeRank;
	
	
	/**
	 * CONSTRUCTOR
	 * @param mg the graph the agent represent
	 * @param rank the rank of the agent
	 */
	public Agent (DinicMainGraph mg,double rank){
		agentId=idCounter;
		idCounter++;
		agentGraph=mg;
		operators=new HashSet<Operator>(mg.getMaingraph().vertexSet());
		this.rank=rank;
		splitable=true;
		edgeRank=1;
		
	}
	/**
	 * GETTER
	 * @return
	 */
	public double getRank() {
		return rank;
	}


	
	/**
	 * CONSTRUCTOR
	 * @param id id of the graph
	 * @param mg the graph the agent represents
	 * @param rank the rank of the graph
	 */
	public Agent (int id,DinicMainGraph mg,double rank){
		this.rank=rank;
		agentGraph=mg;
		operators=new HashSet<Operator>(mg.getMaingraph().vertexSet());
		for (Operator i:operators){
			i.setAgent(agentId);
		}
		
	}
	
	
	public Agent (MainGraph graph, double rank){
		agentId=idCounter;
		idCounter++;
		this.rank = rank;
		try {
			this.operators=new HashSet<Operator>(graph.getMainGraph().vertexSet());
			
		} catch (Exception e) {
			e.printStackTrace();
		}
		for (Operator i : operators){
			i.setAgent(agentId);
		}
		
		this.agentGraph = Translating.ourGraphToDinicGraph(graph);
	}
	
	/**
	 * GETTER
	 * @return
	 */

	public int getAgentId() {
		return agentId;
	}

	/**
	 * GETTER
	 * @return
	 */
	public DinicMainGraph getGraph() {
		return this.agentGraph;
	}

	/**
	 * change the object entirely
	 * @param mg
	 * @param rank
	 */
	public Agent setNew(DinicMainGraph mg, int rank) {
		this.rank=rank;
		agentGraph=mg;
		operators=new HashSet<Operator>(mg.getMaingraph().vertexSet());
		for (Operator i:operators){
			i.setAgent(agentId);
		}
		this.edgeRank = 1;
		return this;
		
	}
	
	@Override
	public String toString() {
		return "agentId=" + agentId  + ", num of operators="+operators.size();
	}
	/**
	 * GETTER
	 * @return
	 */
	public boolean isSplitable()
	{
		return splitable;
	}
	
	
	/**
	 * making agent unsplittable
	 */
	public void unSplitable() {
		splitable = false;
	}
	
	/**
	 * raise the edge edges by 1
	 */
	public void raiseEdgesFromSource() {
		for (FlowingEdge i:agentGraph.getMaingraph().edgesOf(agentGraph.getSource()))
				i.setCapacity(i.getCapacity()+1);
		for (FlowingEdge i:agentGraph.getMaingraph().incomingEdgesOf(agentGraph.getSink()))
				i.setCapacity(i.getCapacity()+1);
		edgeRank++;
		
	}
	
	/**
	 * GETTER
	 * @return the edges weight
	 */
	public int getEdgeRank() {
		return edgeRank;
	}
	
	/**
	 * checks if op is int he list of operators
	 * @param op we want to check if contains
	 * @return true or false
	 */
	public boolean hasOperator(Operator op){
		return this.operators.contains(op); 
	}	
	/**
	 * gives id to operators
	 */
	public void putAgentId(){
		for (Operator i:operators){
			i.setAgent(agentId);
		}
	}
	/**
	 * TODO Put here a description of what this method does.
	 *
	 * @return
	 */
	public int getId() {
	    return this.agentId;
	}
	
	/**
	 * removes the source and sink operators
	 * @param source
	 * @param sink
	 */
	public void removeOperators(Operator source, Operator sink) {
		operators.remove(source);
		operators.remove(sink);
	}

}
